home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
JFC.bin
/
StandardDialog.java
< prev
next >
Wrap
Text File
|
1998-06-30
|
15KB
|
440 lines
/*
* @(#)StandardDialog.java 1.23 01/28/98
*
* Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not disclose
* such Confidential Information and shall use it only in accordance with the
* terms of the license agreement you entered into with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
* OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
* LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR
* ITS DERIVATIVES.
*
*/
package com.sun.java.swing;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import com.sun.java.swing.event.*;
import com.sun.java.swing.plaf.*;
/**
A base class for a standard dialog box to request an object.
It can be used in either
a modal or non-modal fashion. If it has any change listeners, change
Events will be sent to them
when the OK or Apply buttons are pressed. If there are to be no item listeners
then the dialog box should be created with modal==true and the start
method will block until a new object is entered.
<p>
The standard pattern for doing a modal dialog box is:
<pre>Component c = <whatever is supposed to be inside the box>
StandardDialog d = new StandardDialog(parent, c, true);
d.setTitle("whatever"); // if needed
d.setDescription("paragraph to go at the top of the box"); // if needed
d.show();
value = c.getValue();
</pre>
<p>
In normal usage, the static convenience method ask that appears
in many standard Choosers is the easiest way to request objects:
<p><pre>
String c = StringChooser.ask(null, "What is your favorite color?",
"purple", 40, null);
</pre><p>
@see FileChooser
@see ColorChooser
@see StringChooser
@see DateChooser
@see FontChooser
@author James Gosling
*/
public class StandardDialog extends Dialog {
// Needs much more flexible UI hooks
private Component body;
private int style;
private boolean locationUnknown = true;
private PaintRef backgroundPaint;
private GridBagConstraints cons;
private boolean canceled = false;
private static Font dialogFont = new Font ("Dialog", 0, 11);
private static Component defaultParent;
private AbstractButton[] buttonList;
private int buttonIndex = -1;
private Object description;
private UI ui;
private Icon descriptiveIcon;
private Component cparent;
public static final int PlainStyle = 0;
public static final int QuestionStyle = 1;
public static final int InformStyle = 2;
public static final int WarnStyle = 3;
public static final int ErrorStyle = 4;
/** Wraps a dialog box around a Component that implents
* the DialogBody interface. The Dialog box has OK, Cancel
* and Apply buttons that cause ItemSelected messages to
* be sent & the window to be closed as appropriate. */
public StandardDialog (Component parent, Component body, boolean modal) {
super(findFrame(parent), " ", false /* modal */ );
cparent = parent != null ? parent : defaultParent;
this.body = body;
setTitle(" ");
updateUI();
// UIManager.addUIChangeListener(this);
}
private static Frame findFrame(Component c) {
if (c == null)
c = defaultParent;
while (c != null && !(c instanceof Frame))
c = c.getParent();
if (defaultParent == null)
defaultParent = c;
return (Frame) c;
}
/** Before the default constructor can be used, a default parent
has to be set up, either by a preceeding constructor invocation
with a non-null parent, or by an explicit call to setDefaultParent.
The dialog will be modal (there's an AWT bug that stops modal-ness
from being changed after the dialog is created) */
public StandardDialog () {
this(null, null, true);
}
/** Convenience method to prompt for a button press.
@param fparent the parent frame for the dialog box.
fparent may be null if a default parent has
been established with StandardDialog
@param description a description string that will be shown
to the user to indicate what is being requested
@param style the style of the box (PlainStyle, QuestionStyle,
InformStyle, WarnStyle, ErrorStyle)
@param buttons the labels to appear on the buttons
@param target the ChangeListener that will be informed if
any button is hit
@return If target is null,
the dialog box will be modal and the method
will return the index of the button pressed,
or -1 if canceled.
Otherwise, the
dialog box is non-modal, the method returns null
immediatly, and the listener is informed when
appropriate. The source of the change event will
be a StandardDialog on which you should call getButtonIndex.
@see StandardDialog
*/
public static int ask(Component parent, String description, int style,
Object buttons[],
ChangeListener target) {
StandardDialog d = new StandardDialog (parent, null, target == null);
d.setDescription(description);
d.setStyle(style);
d.setButtonList(buttons);
if (target != null)
d.addChangeListener(target);
d.start();
if (target != null)
return -1;
d.setVisible(false);
d.dispose();
return d.isCanceled() ? -1 : d.getButtonIndex();
}
/** This class keeps track of a default parent framem, which can be
set with this method. When creating a StandardDialog, if the
parent parameter is null, this default parent will be used. If
the default parent is not set explicitly, it will be implicitly
set if a StandardDialog is created with parent!=null. It'll
make your life simpler if early on in your application (like when
you create your main application Frame) you set the default parent. */
public static void setDefaultParent(Component p) {
defaultParent = p;
}
/** Get the parent that this dialog box was created with. A standard
dialog's parent may be an arbitrary Component, not just a Frame.
This Component is used to calculate the placement of the dialog box.
In contrast, getParent() will return the Frame that contains the
creation parent. */
public Component getCreationParent() {
return cparent;
}
/** Set the style for the dialog box (PlainStyle, QuestionStyle,
InformStyle, WarnStyle, ErrorStyle) */
public void setStyle(int style) {
this.style = style;
}
public int getStyle() {
return style;
}
/** Set a descriptive icon to be used in the dialog box. How it is
used depends on the particular style. Optional. */
public void setDescriptiveIcon(Icon icon) {
descriptiveIcon = icon;
}
public Icon getDescriptiveIcon() {
return descriptiveIcon;
}
/** A standard dialog may have a stack of descriptive information,
usually placed at the top.
@param d An array of descriptive information. Objects which
are subclasses of Component will be used directly,
Arrays of Objects will be traversed and their elements
will be added,
Icons will be used in new JLabels, and
all others will be converted to strings via toString
and used in new JLabels. Strings will be line wrapped
with paragraph breaks at newlines. */
public void setDescription(Object d) {
description = d;
}
/** Similar to setDescription except that instead of replacing
the whole list of descriptive information, it adds to the end. */
public void appendDescription(Object d) {
if (d != null)
if (description == null)
description = d;
else
description = new Object[] {
description, d
};
}
/** Similar to setDescription except that instead of replacing
the whole list of descriptive information, it adds before the
beginning. */
public void prependDescription(Object d) {
if (d != null)
if (description == null)
description = d;
else
description = new Object[] {
d, description
};
}
public Object getDescription() {
return description;
}
/** A standard dialog may have an arbitrary list of buttons placed
at the bottom.
@param bl An array of buttons or button labels. Objects which
are subclasses of AbstractButton will be used directly,
Icons will be used directly as labels on JButtons, and
all others will be converted to strings via toString
and used as the labels for new JButtons. */
public void setButtonList(Object bl[]) {
AbstractButton[] b = new AbstractButton[bl.length];
for (int i = 0; i < bl.length; i++)
if (bl[i] instanceof AbstractButton)
b[i] = (AbstractButton) bl[i];
else if (bl[i] instanceof Icon)
b[i] = new JButton((Icon) bl[i]);
else
b[i] = new JButton(bl[i].toString());
buttonList = b;
}
public AbstractButton[] getButtonList() {
return buttonList;
}
/** When there is an arbitrary button list, the index of the button
that was pressed is available through getButtonIndex. */
public int getButtonIndex() {
return buttonIndex;
}
public void setButtonIndex(int bi) {
buttonIndex = bi;
}
public void updateUI() {
UIFactory fac = UIManager.getDefaultFactory();
Color c = fac.getPaint("dialogforeground", "window_text").getColor();
if (c == SystemColor.window)
c = null;
setForeground(c != null ? c : SystemColor.windowText);
setBackgroundPaint(fac.getPaint("dialogbackground", "window"));
setFont(fac.getFont("dialogfont", "Dialog-11"));
// Can't use UIFactory.getUI since it demands ComponentUIs
String className = fac.getProperty("StandardDialogUI",
"com.sun.java.swing.basic.BasicStandardDialogUI");
try {
Class uiClass = Class.forName(className);
Class createUIArgClass = this.getClass();
java.lang.reflect.Method m = null;
do {
try {
m = uiClass.getMethod("createUI",
/**INDENT** Error@277: Unbalanced parens */
new Class[] {
createUIArgClass
/**INDENT** Warning@279: Extra ) */
});
} catch(NoSuchMethodException nsme) {
// The target class doesn't define createUI(), try its
// parent.
createUIArgClass = createUIArgClass.getSuperclass();
if (createUIArgClass == null) {
System.err.println("createUI() not found in " +
className);
return;
}
}
} while (m == null);
/**INDENT** Error@291: Unbalanced parens */
ui = (UI) (m.invoke(null, new Object[] {
this
/**INDENT** Warning@293: Extra ) */
/**INDENT** Warning@293: Extra ) */
}));
} catch(Throwable cnf) {
cnf.printStackTrace();
return;
}
}
public void dispose() {
// UIManager.removeUIChangeListener(this);
// ui.uninstallUI(this);
super.dispose();
}
private ChangeEvent changeEvent;
private EventListenerList listenerList = new EventListenerList();
public boolean hasChangeListener() {
Object [] o = listenerList.getListenerList();
if (o != null)
for (int i = o.length; (i -= 2) >= 0;)
if (o[i] == ChangeListener.class)
return true;
return false;
}
/**
* Adds a ChangeListener to the button.
*/
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
}
/**
* Removes a ChangeListener from the button.
*/
public void removeChangeListener(ChangeListener l) {
listenerList.remove(ChangeListener.class, l);
}
protected void fireStateChanged() {
// Guaranteed to return a non-null array
Object [] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == ChangeListener.class) {
// Lazily create the event:
if (changeEvent == null)
changeEvent = new ChangeEvent(body == null ?
this :
((Component) (body)));
((ChangeListener) listeners[i + 1]).stateChanged(changeEvent);
}
}
}
public synchronized void notifyChange() {
fireStateChanged();
notifyAll();
}
/** Once the Dialog box is set up, start() pops the dialog box up
and begins the interaction. If the dialog box is modal, start()
doesn't return until the interaction is complete. Otherwise it
returns immediatly and the ChangeListeners will be notified when
a color is selected. */
public synchronized void start() {
ui.start(this);
if (hasChangeListener())
return;
try {
// can't use instanceof EventDispatchThread because the class isn't public
if (Thread.currentThread().getClass().getName().endsWith("EventDispatchThread")) {
EventQueue theQueue = getToolkit().getSystemEventQueue();
while (isVisible()) {
// This is essentially the body of EventDispatchThread
AWTEvent event = theQueue.getNextEvent();
Object src = event.getSource();
// can't call theQueue.dispatchEvent, so I pasted it's body here
/*if (event instanceof ActiveEvent) {
((ActiveEvent) event).dispatch();
} else */ if (src instanceof Component) {
((Component) src).dispatchEvent(event);
} else if (src instanceof MenuComponent) {
((MenuComponent) src).dispatchEvent(event);
} else {
System.err.println("unable to dispatch event: " + event);
}
}
} else
while (isVisible())
wait();
} catch(InterruptedException e){}
}
/** true iff this dialog has been canceled by the user */
public boolean isCanceled() {
return canceled;
}
public void setCanceled(boolean b) {
canceled = b;
}
public Component getBody() {
return body;
}
public void setBackgroundPaint(PaintRef bkg) {
if (backgroundPaint != bkg) {
Color c = bkg.getColor();
setBackground(c != null ? c : SystemColor.window);
backgroundPaint = bkg;
repaint();
}
}
public PaintRef getBackgroundPaint() {
return backgroundPaint;
}
public void paint(Graphics g) {
if (backgroundPaint != null && backgroundPaint.getTile() != null)
backgroundPaint.fill(g, this);
super.paint(g);
}
public void update(Graphics g) {
if (backgroundPaint != null)
backgroundPaint.fill(g, this);
super.paint(g);
}
/** If the component that is the body of a StandardDialog implements to
OKcheck interface, then the isOK() method will be called after the
user has pressed the OK button to determine if it really is OK. */
public static interface OKcheck {
boolean isOK();
}
/** If you want to implement a new user interface for standard dialogs,
this is the interface you have to implement. */
public static interface UI {
/** Once the Dialog box is set up, start() pops the dialog box up
and begins the interaction. If the dialog box is modal, start()
doesn't return until the interaction is complete. Otherwise it
returns immediatly and the ChangeListeners will be notified when
a color is selected. */
public void start(StandardDialog dlg);
}
}